home *** CD-ROM | disk | FTP | other *** search
/ PC User 2003 January / Disc 1 / PCU0103CD1.iso / entertn / demos / files / aomtrial.exe / AOM / AI / SCN18P3.XS < prev    next >
Encoding:
Text File  |  2002-09-11  |  25.9 KB  |  725 lines

  1. //==============================================================================
  2. // Scn18p3: AI Scenario Script for scenario 18 player 3
  3. //==============================================================================
  4. // Need scn lib for some stuff here.
  5. include "scn lib.xs";
  6.  
  7. // Variable for main base.
  8. int gMainBaseID=-1;
  9.  
  10. //==============================================================================
  11. // Set Town Location
  12. //==============================================================================
  13. void setTownLocation(void)
  14. {
  15.    //Look for the "Town Location" marker.
  16.    kbSetTownLocation(kbGetBlockPosition("9959"));
  17. }
  18.  
  19. //==============================================================================
  20. // miscStartup
  21. //==============================================================================
  22. void miscStartup(void)
  23. {
  24.     // Difficulty Level check.
  25.     int difflevel=-1;        
  26.     difflevel=aiGetWorldDifficulty();
  27.  
  28.    //Startup message(s).
  29.    aiEcho("");
  30.    aiEcho("");
  31.    aiEcho("Scn18P3 AI Start, filename='"+cFilename+"'.");
  32.     aiEcho("Difficulty Level="+difflevel+".");
  33.    //Spit out the map size.
  34.    aiEcho("  Map size is ("+kbGetMapXSize()+", "+kbGetMapZSize()+").");
  35.    //Cheat like a bastard.  Once only, though.
  36.    kbLookAtAllUnitsOnMap();
  37.    //Calculate some areas.
  38.    kbAreaCalculate(1200.0);
  39.    //Set our town location.
  40.    setTownLocation();
  41.     //Reset random seed
  42.     aiRandSetSeed();
  43.  
  44.     //Set the base location.
  45.     gMainBaseID=kbBaseGetMainID(cMyID);
  46.  
  47.     // Drop the AI attack response distance for this player to 5 meters, to simulate the surprise thing
  48.     aiSetAttackResponseDistance(10.0);
  49. }
  50.  
  51. //==============================================================================
  52. //==============================================================================
  53. // Attack stuff.
  54. //==============================================================================
  55. //==============================================================================
  56. //Shared variables.
  57. int numberAttacks=0;
  58. int attackPlayerID=-1;
  59.  
  60. //TODO: Decide how to rep attack group size.
  61. int attackMinimumGroupSize=3;
  62. int attackMaximumGroupSize=5;
  63.  
  64. //Attack 1 vars.
  65. int attackPlan1ID=-1;
  66.  
  67. //Attack 2 vars.
  68. int attackPlan2ID=-1;
  69.  
  70. // Defend plans.
  71. int defendPlan1ID=-1;
  72.  
  73. // Route and path vars
  74. int attackRoute1ID=-1;
  75. int attackPath1ID=-1;
  76. int attackRoute2ID=-1;
  77. int attackPath2ID=-1;
  78.  
  79. // Saved plan IDs
  80. int maintainPlan1ID=-1;
  81. int maintainPlan2ID=-1;
  82. int maintainPlan3ID=-1;
  83. int maintainPlan4ID=-1;
  84. int maintainPlanVillagerID=-1;
  85. int exploreID=-1;
  86.  
  87. int attackerUnitTypeID1=cUnitTypeSpearman;
  88. int attackerUnitTypeID2=cUnitTypePetsuchos;
  89. // int attackerUnitTypeID2=cUnitTypeWadjet;
  90.  
  91. // Initial gather percentages
  92. float totalFoodGathererPercentage  = 0.5;
  93. float totalWoodGathererPercentage  = 0.1;
  94. float totalGoldGathererPercentage  = 0.4;
  95. float totalFavorGathererPercentage = 0.0;
  96.  
  97.  
  98. //==============================================================================
  99. // initMainBase - Mike's spiffy function to relocate the main base.
  100. //==============================================================================
  101. void initMainBase()
  102. {
  103.     vector basePosition=kbGetBlockPosition("9960");
  104.  
  105.    // Nuke bases, add one base to rule them all
  106.    kbBaseDestroyAll(cMyID);
  107.  
  108.    gMainBaseID = kbBaseCreate(cMyID, "Base "+kbBaseGetNextID(), basePosition, 50.0);
  109.    
  110.     if (gMainBaseID < 0)
  111.       aiEcho("***** Main base creation failed. *****");
  112.  
  113.    vector baseFront=xsVectorNormalize(kbGetMapCenter()-basePosition);     // Set front
  114.    kbBaseSetFrontVector(cMyID, gMainBaseID, baseFront);                 
  115.    kbBaseSetMaximumResourceDistance(cMyID, gMainBaseID, 50.0);
  116.    kbBaseSetMain(cMyID, gMainBaseID, true);     // Make this the main base
  117.  
  118.    // Add the buildings
  119.    int buildingQuery = -1;
  120.    int count = 0;
  121.    buildingQuery = kbUnitQueryCreate("Building Query");     // All buildings in the base
  122.    configQuery(buildingQuery, cUnitTypeBuilding, -1, cUnitStateAliveOrBuilding, cMyID, basePosition, false, 50.0);
  123.    kbUnitQueryResetResults(buildingQuery);
  124.    count = kbUnitQueryExecute(buildingQuery);
  125.  
  126.    int i = 0;
  127.    int buildingID = -1;
  128.     echoQuery(buildingID);
  129.    for (i=0; < count)
  130.    {
  131.       buildingID = kbUnitQueryGetResult(buildingQuery, i);
  132.       // Add it to the base
  133.       kbBaseAddUnit( cMyID, gMainBaseID, buildingID );
  134.    }
  135. }
  136.  
  137. //==============================================================================
  138. // initEcon
  139. //
  140. // Set Up the initial Economy.
  141. //==============================================================================
  142. void initEcon()
  143. {
  144.    aiEcho("Economy Init.");
  145.  
  146.     /* Don't need this for what we're doing here.
  147.    // Set our update resource handler.
  148.    aiSetUpdateResourceEventHandler("updateResourceHandler");
  149.     */
  150.  
  151.    //-- Setup AI Cost weights.
  152.    kbSetAICostWeight(cResourceFood, 1.5);
  153.    kbSetAICostWeight(cResourceWood, 1.0);
  154.    kbSetAICostWeight(cResourceGold, 1.5);
  155.    kbSetAICostWeight(cResourceFavor, 10.0);
  156.  
  157.    //-- Dont auto gather favor
  158.    //totalFavorGathererPercentage = 0;
  159.  
  160.    //-- Set initial gatherer percentages.
  161.    aiSetResourceGathererPercentage(cResourceFood, totalFoodGathererPercentage, false, cRGPScript);
  162.    aiSetResourceGathererPercentage(cResourceWood, totalWoodGathererPercentage, false, cRGPScript);
  163.    aiSetResourceGathererPercentage(cResourceGold, totalGoldGathererPercentage, false, cRGPScript);
  164.    aiSetResourceGathererPercentage(cResourceFavor, totalFavorGathererPercentage, false, cRGPScript);
  165.    aiNormalizeResourceGathererPercentages(cRGPScript);
  166.  
  167.    aiSetResourceGathererPercentageWeight(cRGPScript, 1);
  168.    aiSetResourceGathererPercentageWeight(cRGPCost, 0);
  169.  
  170.    //-- Set up the initial resource subtype breakdowns - all farming, all the time.
  171.     // aiSetResourceBreakdown(cResourceFood, cAIResourceSubTypeEasy, 1, 50, 0.0, gMainBaseID);
  172.     // aiSetResourceBreakdown(cResourceFood, cAIResourceSubTypeHunt, 1, 50, 0.1, gMainBaseID);
  173.     aiSetResourceBreakdown(cResourceFood, cAIResourceSubTypeFarm, 1, 50, 1.0, gMainBaseID);
  174.     // aiSetResourceBreakdown(cResourceFood, cAIResourceSubTypeFish, 1, 50, 1.0, gMainBaseID);
  175.     aiSetResourceBreakdown(cResourceWood, cAIResourceSubTypeEasy, 1, 50, 1.0, gMainBaseID);
  176.     aiSetResourceBreakdown(cResourceGold, cAIResourceSubTypeEasy, 1, 50, 1.0, gMainBaseID);
  177.    aiSetResourceBreakdown(cResourceFavor, cAIResourceSubTypeEasy, 1, 50, 1.0, gMainBaseID);
  178.     
  179.    //-- Set up auto-gather escrows
  180.    aiSetAutoGatherEscrowID(cRootEscrowID);
  181.    aiSetAutoFarmEscrowID(cRootEscrowID);
  182.  
  183.     //Allocate all resources to the root escrow by setting percentage of military/economy to 0.
  184.     kbEscrowSetPercentage( cEconomyEscrowID, cAllResources, 0.0 );
  185.     kbEscrowSetPercentage( cMilitaryEscrowID, cAllResources, 0.0 );
  186.  
  187.     //-- create a herd plan to gather any herdables that we encounter.
  188.    int herdPlanID=aiPlanCreate("HerdThings", cPlanHerd);
  189.    if (herdPlanID >= 0)
  190.    {
  191.       aiPlanAddUnitType(herdPlanID, cUnitTypeHerdable, 0, 100, 100);
  192.       aiPlanSetVariableInt(herdPlanID, cHerdPlanBuildingTypeID, 0, cUnitTypeSettlementLevel1);
  193.       aiPlanSetActive(herdPlanID);
  194.    }
  195.  
  196.     //Allocate all resources
  197.    kbEscrowAllocateCurrentResources();
  198. }
  199.  
  200. //==============================================================================
  201. // initAttack: Creates attack routes, etc.
  202. //==============================================================================
  203. void initAttack(int playerID=-1)
  204. {
  205.    //Destroy all previous attacks (if this isn't the player we're already attacking.
  206.    if (playerID != attackPlayerID)
  207.    {
  208.       //Reset the attack player ID.
  209.       attackPlayerID=-1;
  210.       //Destroy any previous attack plan.
  211.       aiPlanDestroy(attackPlan1ID);
  212.       attackPlan1ID=-1;
  213.       aiPlanDestroy(attackPlan2ID);
  214.       attackPlan2ID=-1;
  215.   
  216.       //Destroy our previous attack paths.
  217.       kbPathDestroy(attackPath1ID);
  218.       attackPath1ID=-1;
  219.       kbPathDestroy(attackPath2ID);
  220.       attackPath2ID=-1;
  221.  
  222.       //Destroy our previous attack routes.
  223.       attackRoute1ID=-1;
  224.       attackRoute2ID=-1;
  225.  
  226.       //Reset the number of attacks.
  227.       numberAttacks=0;
  228.    }
  229.  
  230.    //Save the player to attack.
  231.    attackPlayerID=playerID;
  232.  
  233.    vector gatherPoint=kbGetBlockPosition("6456");
  234.        
  235.     //Setup attack path 1
  236.    attackPath1ID=kbPathCreate("Attack Path");
  237.    kbPathAddWaypoint(attackPath1ID, kbGetBlockPosition("6456"));
  238.     kbPathAddWaypoint(attackPath1ID, kbGetBlockPosition("6457"));
  239.    
  240.     //Create attack route 1.
  241.    attackRoute1ID=kbCreateAttackRouteWithPath("Attack Route 1", gatherPoint, kbGetBlockPosition("6458"));
  242.    
  243.     if (attackRoute1ID >= 0)
  244.       kbAttackRouteAddPath(attackRoute1ID, attackPath1ID);
  245.  
  246.    //Setup attack path 2 - go south
  247.     /*
  248.    attackPath2ID=kbPathCreate("Attack Path South");
  249.  
  250.     kbPathAddWaypoint(attackPath1ID, kbGetBlockPosition("1851"));
  251.     kbPathAddWaypoint(attackPath1ID, kbGetBlockPosition("1853"));
  252.     kbPathAddWaypoint(attackPath1ID, kbGetBlockPosition("1849"));
  253.     kbPathAddWaypoint(attackPath1ID, kbGetBlockPosition("3080"));
  254.     kbPathAddWaypoint(attackPath1ID, kbGetBlockPosition("3073"));
  255.  
  256.    //Create attack route 2.
  257.    attackRoute2ID=kbCreateAttackRouteWithPath("Attack Route 2", gatherPoint, kbGetBlockPosition("3075"));
  258.        
  259.     if (attackRoute2ID >= 0)
  260.       kbAttackRouteAddPath(attackRoute2ID, attackPath2ID);
  261.     */
  262. }
  263.  
  264. //==============================================================================
  265. // setupAttack
  266. //==============================================================================
  267. bool setupAttack(int playerID=-1)
  268. {
  269.     // Difficulty Level check.
  270.     int difflevel=-1;        
  271.     difflevel=aiGetWorldDifficulty();
  272.  
  273.     // int randomPath=aiRandInt(2);
  274.  
  275.    //Info.
  276.     aiEcho("Attacking Player "+playerID+".");
  277.  
  278.    //If the player to attack doesn't match, init the attack.
  279.    if (attackPlayerID != playerID)
  280.    {
  281.       initAttack(playerID);
  282.       if (attackPlayerID < 0)
  283.          return(false);
  284.    }
  285.  
  286.    //Create an attack plan.
  287.    int newAttackPlanID=aiPlanCreate("Attack Player"+attackPlayerID+" Attempt"+numberAttacks, cPlanAttack);
  288.    if (newAttackPlanID < 0)
  289.       return(false);
  290.  
  291.    //Target player (required).  This must work.
  292.    if (aiPlanSetVariableInt(newAttackPlanID, cAttackPlanPlayerID, 0, attackPlayerID) == false)
  293.       return(false);
  294.  
  295.    //Gather point.
  296.     vector gatherPoint=kbGetBlockPosition("3081");
  297.  
  298.     //Set the target type.  This must work.
  299.    if (aiPlanSetNumberVariableValues(newAttackPlanID, cAttackPlanTargetTypeID, 2, true) == false)
  300.       return(false);
  301.  
  302.    //Unit types to attack.
  303.    aiPlanSetVariableInt(newAttackPlanID, cAttackPlanTargetTypeID, 0, cUnitTypeUnit);
  304.     aiPlanSetVariableInt(newAttackPlanID, cAttackPlanTargetTypeID, 1, cUnitTypeBuilding);
  305.  
  306.     aiPlanSetVariableInt(newAttackPlanID, cAttackPlanAttackRouteID, 0, attackRoute1ID);
  307.  
  308.     /*
  309.    //Attack route.
  310.    if (randomPath == 0)
  311.     {
  312.       aiPlanSetVariableInt(newAttackPlanID, cAttackPlanAttackRouteID, 0, attackRoute1ID);
  313.     }
  314.    else
  315.     {
  316.       aiPlanSetVariableInt(newAttackPlanID, cAttackPlanAttackRouteID, 0, attackRoute2ID);
  317.     }
  318.     */
  319.  
  320.    //Set the gather point and gather point distance.
  321.    aiPlanSetVariableVector(newAttackPlanID, cAttackPlanGatherPoint, 0, gatherPoint);
  322.    aiPlanSetVariableFloat(newAttackPlanID, cAttackPlanGatherDistance, 0, 30.0);
  323.  
  324.    //Set up the attack route usage pattern.
  325.    aiPlanSetVariableInt(newAttackPlanID, cAttackPlanAttackRoutePattern, 0, cAttackPlanAttackRoutePatternRandom);
  326.    
  327.     //Add the unit types to the plan 
  328.     if ( difflevel < 2 )
  329.     {
  330.         aiPlanAddUnitType(newAttackPlanID, attackerUnitTypeID1, 4, 12, 12);
  331.         aiPlanAddUnitType(newAttackPlanID, attackerUnitTypeID2, 0, 2, 2);
  332.     }
  333.     else if ( difflevel == 2 )
  334.     {
  335.         aiPlanAddUnitType(newAttackPlanID, attackerUnitTypeID1, 4, 16, 16);
  336.         aiPlanAddUnitType(newAttackPlanID, attackerUnitTypeID2, 0, 4, 4);
  337.     }
  338.     else
  339.     {
  340.         aiPlanAddUnitType(newAttackPlanID, attackerUnitTypeID1, 4, 16, 16);
  341.         aiPlanAddUnitType(newAttackPlanID, attackerUnitTypeID2, 0, 6, 6);
  342.     }
  343.  
  344.    //Set the initial position.
  345.    aiPlanSetInitialPosition(newAttackPlanID, gatherPoint);
  346.    //Plan requires all need units to work (can be false).
  347.    aiPlanSetRequiresAllNeedUnits(newAttackPlanID, true);
  348.    //Activate the plan.
  349.    aiPlanSetActive(newAttackPlanID);
  350.  
  351.    //Now, save the attack plan ID appropriately.
  352.    aiPlanSetOrphan(attackPlan1ID, true);
  353.    attackPlan1ID=newAttackPlanID;
  354.  
  355.    //Increment our overall number of attacks.
  356.    numberAttacks++;
  357. }
  358.  
  359. //==============================================================================
  360. // createUnitProgression
  361. //==============================================================================
  362. int createUnitProgression(int unitTypeID=-1, string name="BUG")
  363. {
  364.    int pID=aiPlanCreate(name, cPlanProgression);
  365.    
  366.     if (pID < 0)
  367.       return(-1);
  368.  
  369.    //This is a military plan.
  370.    //aiPlanSetMilitary(pID, true);
  371.    //Set it for the building that we get our unit from.
  372.    aiPlanSetVariableInt(pID, cProgressionPlanGoalUnitID, 0, kbTechTreeGetUnitIDByTrain(unitTypeID));
  373.    
  374.     //Build it in our main base using the root escrow.
  375.     aiPlanSetBaseID(pID, gMainBaseID);
  376.     aiPlanSetEscrowID(pID, cRootEscrowID);
  377.    
  378.     //Go.
  379.    aiPlanSetActive(pID);
  380.    return(pID);
  381. }
  382.  
  383. //==============================================================================
  384. // createTechProgression
  385. //==============================================================================
  386. int createTechProgression(int techID=-1, string name="BUG", int researchFromProto=-1)
  387. {
  388.    //Check for old plan.
  389.     int oldPlanID=aiPlanGetIDByTypeAndVariableType(cPlanProgression, cProgressionPlanGoalTechID, techID);
  390.    if(oldPlanID != -1)
  391.    {
  392.       aiEcho("createTechProgression: already have a plan("+oldPlanID+") for this Tech("+techID+").");
  393.       return(oldPlanID);
  394.    }
  395.    
  396.     //Create a new one.
  397.    int pID=aiPlanCreate(name, cPlanProgression);
  398.    if (pID < 0)
  399.    {
  400.       aiEcho("createTechProgression: couldn't create Progression.");
  401.       return(-1);
  402.    }
  403.    //This is a military plan.
  404.    //aiPlanSetMilitary(pID, true);
  405.    aiPlanSetVariableInt(pID, cProgressionPlanGoalTechID, 0, techID);
  406.    aiPlanSetVariableInt(pID, cProgressionPlanBuildingPref, 0, researchFromProto);
  407.    
  408.     //Build it in our main base using the root escrow.
  409.    aiPlanSetBaseID(pID, gMainBaseID);
  410.     aiPlanSetEscrowID(pID, cRootEscrowID);
  411.  
  412.    //Go.
  413.    aiPlanSetActive(pID);
  414.    aiEcho("createTechProgression: creating Tech Progression("+name+") to TechID("+techID+").");
  415.    return(pID);
  416. }
  417.  
  418. //==============================================================================
  419. // Favor cheat - favor every so often.
  420. //==============================================================================
  421. rule favorCheat
  422.    minInterval 60
  423.    active
  424.    group AttackRules
  425. {
  426.     // Difficulty Level check.
  427.     int difflevel=-1;        
  428.     difflevel=aiGetWorldDifficulty();
  429.  
  430.     // Cheat for favor every 60 seconds.  Them pirates are bastards.
  431.     aiResourceCheat( 3, cResourceFavor, 50.0 );
  432.  
  433.     // Little extra gold to smooth the lazur crocs...
  434.     if ( difflevel == 2 )
  435.     {
  436.         aiResourceCheat( 3, cResourceGold, 100.0 );
  437.     }
  438.     else if ( difflevel == 3 )
  439.     {
  440.         aiResourceCheat( 3, cResourceGold, 200.0 );
  441.     }
  442. }
  443.  
  444. //==============================================================================
  445. // Attack Generator 1 - Send dudes now!  Or, well, soon,
  446. //==============================================================================
  447. rule attackGenerator1
  448.    minInterval 90
  449.    inactive
  450.    group AttackRules
  451. {
  452.    //See how many "idle" attack plans we have.  Don't create any more if we have
  453.    //idle plans.
  454.    int numberIdleAttackPlans=aiGetNumberIdlePlans(cPlanAttack);
  455.  
  456.    if (numberIdleAttackPlans > 0)
  457.       return;
  458.  
  459.    //If we have enough unassigned military units, create a new attack plan.
  460.    int numberAvailableUnits=aiNumberUnassignedUnits(attackerUnitTypeID1);
  461.    aiEcho("There are "+numberAvailableUnits+" spearmen available for a new attack.");
  462.    
  463.     if (numberAvailableUnits >= 4)
  464.         setupAttack(1);
  465. }
  466.  
  467.  
  468. //==============================================================================
  469. // Maintain Scarabs, starting four minutes after being alerted.
  470. //==============================================================================
  471. /*
  472. rule maintainScarabs
  473.    minInterval 240
  474.    inactive
  475. {
  476.     vector gatherPointMyth=kbGetBlockPosition("1853");
  477.  
  478.     // Two should be plenty.
  479.    maintainPlan4ID=aiPlanCreate("Maintain 2 "+kbGetProtoUnitName(attackerUnitTypeID4), cPlanTrain);
  480.    if (maintainPlan4ID >= 0)
  481.    {
  482.         //Must set the type of unit to train.
  483.       aiPlanSetVariableInt(maintainPlan4ID, cTrainPlanUnitType, 0, attackerUnitTypeID4);
  484.       //You can limit the number of units that are ever trained by this plan with this call.
  485.       //aiPlanSetVariableInt(maintainPlanID, cTrainPlanNumberToTrain, 0, 25);
  486.       //Set the number of units to maintain in the world at one time.
  487.       aiPlanSetVariableInt(maintainPlan4ID, cTrainPlanNumberToMaintain, 0, 2);
  488.       //Don't train units too fast
  489.       aiPlanSetVariableInt(maintainPlan4ID, cTrainPlanFrequency, 0, 90);
  490.       //Set a gather point.
  491.       aiPlanSetVariableVector(maintainPlan4ID, cTrainPlanGatherPoint, 0, gatherPointMyth);
  492.       //Activate the plan.
  493.       aiPlanSetActive(maintainPlan4ID);
  494.    }
  495.  
  496.     // While we're here, destroy the defend plan at the gate.  It should have been
  497.     // there long enough to cover the builders.
  498.     aiPlanDestroy(defendPlan1ID);
  499.     xsDisableSelf();
  500. }
  501. */
  502.  
  503.  
  504. //==============================================================================
  505. // armoryUpgrades, oh yeah!  Six minutes after AI is alerted, if it's still got
  506. // an armory.  And if it doesn't, it should rebuild one, even!
  507. //==============================================================================
  508. /*
  509. rule armoryUpgrades
  510.    minInterval 360
  511.    inactive
  512. {
  513.     aiEcho("*** GETTING ARMORY UPGRADES ***");
  514.     createTechProgression(cTechBronzeWeapons, "Research Bronze Weapons", cUnitTypeArmory);
  515.     createTechProgression(cTechBronzeMail, "Research Bronze Mail", cUnitTypeArmory);
  516.     createTechProgression(cTechCopperShields, "Research Copper Shields", cUnitTypeArmory);
  517.  
  518.     xsDisableSelf();
  519. }
  520. */
  521.  
  522. //==============================================================================
  523. // startAttacks - fires when the player lands.
  524. //==============================================================================
  525. void startAttacks( int parameter=-1 )
  526. {
  527.     aiEcho("*** P3 Attacks now Possible ***");
  528.  
  529.     // Lots more villagers maintained.
  530.     aiPlanSetVariableInt(maintainPlanVillagerID, cTrainPlanNumberToMaintain, 0, 18);
  531.  
  532.     /*
  533.     // Defend plan at the main gate 
  534.    defendPlan1ID=aiPlanCreate("Gate Defense", cPlanDefend);
  535.    if (defendPlan1ID >= 0)
  536.    {
  537.       //Main gate location
  538.       vector defendPlanSpot=kbGetBlockPosition("3080");
  539.  
  540.       //Add the unit(s).
  541.       aiPlanAddUnitType(defendPlan1ID, attackerUnitTypeID1, 0, 3, 3);
  542.         aiPlanAddUnitType(defendPlan1ID, attackerUnitTypeID2, 0, 2, 2);
  543.         
  544.       //Setup the vars - priority is slightly higher than the attack plans.
  545.       aiPlanSetDesiredPriority(defendPlan1ID, 60);
  546.       aiPlanSetVariableVector(defendPlan1ID, cDefendPlanDefendPoint, 0, defendPlanSpot);
  547.       aiPlanSetVariableFloat(defendPlan1ID, cDefendPlanEngageRange, 0, 15);
  548.       aiPlanSetActive(defendPlan1ID);
  549.     }
  550.     */
  551.  
  552.     // Create an explore plan with a single spearman.
  553.    exploreID = aiPlanCreate("Explore", cPlanExplore);
  554.    if(exploreID >= 0)
  555.    {
  556.       aiPlanAddUnitType(exploreID, attackerUnitTypeID1, 1, 1);
  557.       aiPlanSetActive(exploreID);
  558.    }
  559.  
  560.    //-- Build a tower near the center of the lower route.
  561.     /*
  562.    int buildTower = aiPlanCreate("Build Tower", cPlanBuild);
  563.    if(buildTower >= 0)
  564.    {
  565.       //BP Type and Priority.
  566.       aiPlanSetVariableInt(buildTower, cBuildPlanBuildingTypeID, 0, cUnitTypeTower);
  567.       aiPlanSetDesiredPriority(buildTower, 75);
  568.       aiPlanSetVariableVector(buildTower, cBuildPlanCenterPosition, 0, TowerPoint);
  569.         aiPlanSetVariableFloat(buildTower, cBuildPlanCenterPositionDistance, 0, 5);
  570.       aiPlanAddUnitType(buildTower, kbTechTreeGetUnitIDTypeByFunctionIndex(cUnitFunctionBuilder, 0), 2, 2, 2);
  571.       aiPlanSetEscrowID(buildTower, cRootEscrowID);
  572.       aiPlanSetActive(buildTower);
  573.    }
  574.     */
  575.  
  576.     // Enable attacks
  577.     xsEnableRule("attackGenerator1");
  578.     // xsEnableRule("maintainScarabs");
  579.     // xsEnableRule("armoryUpgrades");
  580.  
  581.     // Mmm, unit upgrades.  Let's go!
  582.     // createTechProgression(cTechHeavySpearmen, "Research up to Heavy Spearmen", cUnitTypeBarracks);
  583.     // createTechProgression(cTechHeavySlingers, "Research up to Medium Slingers", cUnitTypeBarracks);
  584.  
  585.     // Attack response range increases to 20.
  586.     aiSetAttackResponseDistance(25.0);
  587. }
  588.  
  589. //==============================================================================
  590. // MAIN.
  591. //==============================================================================
  592. void main(void)
  593. {
  594.     // Difficulty Level check.
  595.     int difflevel=-1;        
  596.     difflevel=aiGetWorldDifficulty();
  597.  
  598.    //Startup.
  599.    miscStartup();
  600.     initMainBase();
  601.     initEcon();
  602.  
  603.    //Gather Points
  604.    vector gatherPointVillager=kbGetBlockPosition("9960");
  605.     vector gatherPointMilitary1=kbGetBlockPosition("6455");
  606.     vector gatherPointMilitary2=kbGetBlockPosition("9958");
  607.  
  608.    maintainPlanVillagerID=aiPlanCreate("Maintain Villagers", cPlanTrain);
  609.    if (maintainPlanVillagerID >= 0)
  610.    {
  611.         //Must set the type of unit to train.
  612.       aiPlanSetVariableInt(maintainPlanVillagerID, cTrainPlanUnitType, 0, cUnitTypeVillagerEgyptian);
  613.       //You can limit the number of units that are ever trained by this plan with this call.
  614.       //aiPlanSetVariableInt(maintainPlanID, cTrainPlanNumberToTrain, 0, 25);
  615.       //Set the number of units to maintain in the world at one time.
  616.       aiPlanSetVariableInt(maintainPlanVillagerID, cTrainPlanNumberToMaintain, 0, 6);
  617.       //Don't train units faster than every 20 seconds
  618.       aiPlanSetVariableInt(maintainPlanVillagerID, cTrainPlanFrequency, 0, 20);
  619.       //Set a gather point.
  620.       aiPlanSetVariableVector(maintainPlanVillagerID, cTrainPlanGatherPoint, 0, gatherPointVillager);
  621.       //Activate the plan.
  622.       aiPlanSetActive(maintainPlanVillagerID);
  623.    }
  624.  
  625.    maintainPlan1ID=aiPlanCreate("Maintain "+kbGetProtoUnitName(attackerUnitTypeID1), cPlanTrain);
  626.    if (maintainPlan1ID >= 0)
  627.    {
  628.         //Must set the type of unit to train.
  629.       aiPlanSetVariableInt(maintainPlan1ID, cTrainPlanUnitType, 0, attackerUnitTypeID1);
  630.       //You can limit the number of units that are ever trained by this plan with this call.
  631.       //aiPlanSetVariableInt(maintainPlanID, cTrainPlanNumberToTrain, 0, 25);
  632.       //Set the number of units to maintain in the world at one time.
  633.  
  634.         if ( difflevel < 2 )
  635.         {
  636.             aiPlanSetVariableInt(maintainPlan1ID, cTrainPlanNumberToMaintain, 0, 12);
  637.             aiPlanSetVariableInt(maintainPlan1ID, cTrainPlanFrequency, 0, 30);
  638.         }
  639.         else
  640.         {
  641.             aiPlanSetVariableInt(maintainPlan1ID, cTrainPlanNumberToMaintain, 0, 16);
  642.             aiPlanSetVariableInt(maintainPlan1ID, cTrainPlanFrequency, 0, 20);
  643.         }
  644.       
  645.       //Set a gather point.
  646.       aiPlanSetVariableVector(maintainPlan1ID, cTrainPlanGatherPoint, 0, gatherPointMilitary1);
  647.       //Activate the plan.
  648.       aiPlanSetActive(maintainPlan1ID);
  649.    }
  650.  
  651.     maintainPlan2ID=aiPlanCreate("Maintain 2 "+kbGetProtoUnitName(attackerUnitTypeID2), cPlanTrain);
  652.    if (maintainPlan2ID >= 0)
  653.    {
  654.         //Must set the type of unit to train.
  655.       aiPlanSetVariableInt(maintainPlan2ID, cTrainPlanUnitType, 0, attackerUnitTypeID2);
  656.       //You can limit the number of units that are ever trained by this plan with this call.
  657.       //aiPlanSetVariableInt(maintainPlanID, cTrainPlanNumberToTrain, 0, 25);
  658.       //Set the number of units to maintain in the world at one time.
  659.  
  660.         if ( difflevel < 2 )
  661.         {
  662.             aiPlanSetVariableInt(maintainPlan2ID, cTrainPlanNumberToMaintain, 0, 2);
  663.             aiPlanSetVariableInt(maintainPlan2ID, cTrainPlanFrequency, 0, 60);
  664.         }
  665.         else if ( difflevel == 2 )
  666.         {
  667.             aiPlanSetVariableInt(maintainPlan2ID, cTrainPlanNumberToMaintain, 0, 4);
  668.             aiPlanSetVariableInt(maintainPlan2ID, cTrainPlanFrequency, 0, 30);
  669.         }
  670.         else
  671.         {
  672.             aiPlanSetVariableInt(maintainPlan2ID, cTrainPlanNumberToMaintain, 0, 6);
  673.             aiPlanSetVariableInt(maintainPlan2ID, cTrainPlanFrequency, 0, 20);
  674.         }
  675.       //Set a gather point.
  676.       aiPlanSetVariableVector(maintainPlan2ID, cTrainPlanGatherPoint, 0, gatherPointMilitary2);
  677.       //Activate the plan.
  678.       aiPlanSetActive(maintainPlan2ID);
  679.    }
  680.     
  681.     /* 
  682.     // Create a fishing plan.
  683.     int fishGatherer = kbTechTreeGetUnitIDTypeByFunctionIndex(cUnitFunctionFish, 0);
  684.     int fishPlanID=aiPlanCreate("FishPlan", cPlanFish);
  685.  
  686.     if (fishPlanID >= 0)
  687.     {
  688.         aiEcho("Setting up the Fishing Plan.");
  689.       aiPlanSetDesiredPriority(fishPlanID, 70);
  690.         aiPlanSetVariableVector(fishPlanID, cFishPlanLandPoint, 0, kbBaseGetLocation(cMyID, gMainBaseID));
  691.         
  692.         //-- If you don't explicitly set the water point, the plan will find one for you.
  693.         aiPlanSetVariableBool(fishPlanID, cFishPlanAutoTrainBoats, 0, false);   // I'm going to have a  maintain plan for fishing + scouting combined
  694.         aiPlanSetEscrowID(fishPlanID, cRootEscrowID);
  695.  
  696.         aiPlanAddUnitType(fishPlanID, fishGatherer, 3, 3, 3);
  697.         aiPlanSetActive(fishPlanID);
  698.     }
  699.     */
  700.  
  701.     // Empower the settlement 
  702.     int empowerPlan1ID=aiPlanCreate("EmpowerPlan", cPlanEmpower);
  703.     if (empowerPlan1ID >= 0)
  704.     {
  705.         aiPlanSetDesiredPriority(empowerPlan1ID, 50);
  706.         aiPlanAddUnitType(empowerPlan1ID, cUnitTypePharaoh, 1, 1, 1);
  707.         aiPlanSetVariableInt(empowerPlan1ID, cEmpowerPlanTargetTypeID, 0, cUnitTypeSettlementLevel1);
  708.         aiPlanSetActive(empowerPlan1ID);
  709.     }
  710.  
  711.     // Empower a barracks
  712.     int empowerPlan2ID=aiPlanCreate("EmpowerPlan", cPlanEmpower);
  713.     if (empowerPlan2ID >= 0)
  714.     {
  715.         aiPlanSetDesiredPriority(empowerPlan2ID, 50);
  716.         aiPlanAddUnitType(empowerPlan2ID, cUnitTypePriest, 1, 1, 1);
  717.         aiPlanSetVariableInt(empowerPlan2ID, cEmpowerPlanTargetTypeID, 0, cUnitTypeBarracks);
  718.         aiPlanSetActive(empowerPlan2ID);
  719.     }
  720.  
  721.     // Basic tech progressions to upgrade our operations (better gold mining and farms)
  722.     createTechProgression(cTechPickaxe, "Research up to Shaft Mine", cUnitTypeMiningCamp);
  723.     createTechProgression(cTechIrrigation, "Research up to Irrigation", cUnitTypeGranary);
  724. }
  725.